﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevComponents.Editors;
using Kugar.Core.ExtMethod;
using DevComponents.Editors.DateTimeAdv;
using DevComponents.DotNetBar.Controls;
using Kugar.Core.Collections;
using Kugar.Core.Enums;
using DevComponents.DotNetBar;


namespace Kugar.ERPFramework.View.WinForm
{

    public class ControlFieldsManager : FieldsManager
    {
        public bool AddField(ControlFieldConfigBase fieldConfig)
        {
            return base.OnAddField(fieldConfig);
        }
    }


    /// <summary>
    ///     普通控件字段的基类
    /// </summary>
    public abstract class ControlFieldConfigBase : FieldConfig
    {
        private Control _labelCtrl;
        private Control _editorCtrl;

        private Lazy<Dictionary<string, object>> _otherInfo = new Lazy<Dictionary<string, object>>(() => { return new Dictionary<string, object>(StringComparer.CurrentCultureIgnoreCase); });
        private DataFetcherManager _dataFetcher = null;

        public ControlFieldConfigBase(string id, object bindingObj = null)
            : base(id,bindingObj)
        {
            //OtherInfo = new Dictionary<string, object>(StringComparer.CurrentCultureIgnoreCase);

            //DataFetchMapping = new List<FillMapping>();

            _dataFetcher =  new DataFetcherManager(this);

            _dataFetcher.DataFetherEnabledChanged += new EventHandler(_dataFetcher_DataFetherEnabledChanged);

            _dataFetcher.DataFetherEnabled = EnabledEx.Auto;


        }

        
        public  override object Value
        {
            get
            {
                object value = null;

                if (EditorCtrl != null)
                {
                    EditorCtrl.Invoke(() => { value = OnGetControlValue(); });
                }
                else
                {
                    value = OnGetBindObjectValue();
                }

                return value;
            }
            set
            {
                if (BindingData != null)
                {
                    object oldValue = null;

                    try
                    {
                        oldValue = this.Value;
                    }
                    catch (Exception)
                    {
                        oldValue = null;
                    }

                    if (value == DBNull.Value)
                    {
                        value = null;
                    }

                    if (oldValue != value && OnValueChanging(value, oldValue))
                    {
                        base.OnSetBindObjectValue(value);

                        if (EditorCtrl!=null && EditorCtrl.FindForm() != null)
                        {
                            try
                            {
                                EditorCtrl.Invoke(() => { OnSetControlValue(value); });
                            }
                            catch (InvalidOperationException)
                            {
                            }
                            
                        }

                        OnValueChanged();
                    }


                }
            }
        }

        /// <summary>
        ///     编辑控件,不建议直接调用该属性
        /// </summary>
        [Obsolete("不建议直接调用该属性")]
        [Browsable(false)]
        public Control EditorCtrl
        {
            set
            {

                if (_editorCtrl != value)
                {
                    UnSetEditorEvent();

                    _editorCtrl = value;

                    SetEditorEvent();

                    OnEditorCtrlChanged();
                }
            }
            get { return _editorCtrl; }
        }

        /// <summary>
        ///     标题控件,不建议直接调用该属性
        /// </summary>
        [Browsable(false)]
        [Obsolete("不建议直接调用该属性")]
        public Control LabelCtrl
        {
            set
            {
                if (_labelCtrl!=value)
                {
                    _labelCtrl = value;


                    if (value != null)
                    {
                        _labelCtrl.Text = this.LabelText;
                    }

                    OnLabelControlChanged();
                }
            }
            get { return _labelCtrl; }
        }

        public Font LabelFont
        {
            get
            {
                if (LabelCtrl!=null)
                {
                    return LabelCtrl.Font;
                }
                else
                {
                    return null;
                }
            }
            set
            {
                if (LabelCtrl!=null)
                {
                    LabelCtrl.Font = value;
                }
            }
        }

        public Font EditorFont
        {
            get
            {
                if (EditorCtrl != null)
                {
                    return EditorCtrl.Font;
                }
                else
                {
                    return null;
                }
            }
            set
            {
                if (EditorCtrl != null)
                {
                    EditorCtrl.Font = value;
                }
            }
        }

        public Color LabelForeColor
        {
            get
            {
                if (LabelCtrl != null)
                {
                    return LabelCtrl.ForeColor;
                }
                else
                {
                    return Color.Black;
                }
            }
            set
            {
                if (LabelCtrl != null)
                {
                    LabelCtrl.ForeColor = value;
                }
            }
        }

        public Color EditorForeColor
        {
            get
            {
                if (EditorCtrl != null)
                {
                    return EditorCtrl.ForeColor;
                }
                else
                {
                    return Color.Black;
                }
            }
            set
            {
                if (EditorCtrl != null)
                {
                    EditorCtrl.ForeColor = value;
                }
            }
        }

        public Color LabelBackColor
        {
            get
            {
                if (LabelCtrl != null)
                {
                    return LabelCtrl.BackColor;
                }
                else
                {
                    return Color.Transparent;
                }
            }
            set
            {
                if (LabelCtrl != null)
                {
                    LabelCtrl.BackColor = value;
                }
            }
        }

        public Color EditorBackColor
        {
            get
            {
                if (EditorCtrl != null)
                {
                    return EditorCtrl.BackColor;
                }
                else
                {
                    return Color.White;
                }
            }
            set
            {
                if (EditorCtrl != null)
                {
                    EditorCtrl.BackColor = value;
                }
            }
        }

        public Dictionary<string, object> OtherInfo { get { return _otherInfo.Value; } }

        public DataFetcherManager DataFetcher { get { return _dataFetcher; } }

        public event EventHandler EditorGetFocus;

        public event EventHandler EditorLostFocus;

        public EventHandler EditorCtrlChanged;

        public EventHandler LabelCtrlChanaged;

        internal abstract void ApplyToControl();

        protected abstract object OnGetControlValue();

        protected abstract void OnSetControlValue(object value);

        protected override void OnLabelTextChanged()
        {
            if (LabelCtrl != null)
            {
                this.LabelCtrl.Invoke(() =>
                {
                    LabelCtrl.Text = base.LabelText;
                });
            }

            base.OnLabelTextChanged();
        }

        protected virtual void OnLabelControlChanged()
        {
            if (LabelCtrlChanaged != null)
            {
                if (LabelCtrl != null)
                {
                    LabelCtrl.RaiseEvent(LabelCtrlChanaged, this, EventArgs.Empty);
                }
            }
        }

        protected override void OnValueChanged()
        {
            if (EditorCtrl != null && EditorCtrl.FindForm() != null)
            {
                try
                {
                    EditorCtrl.Invoke(() => { base.OnValueChanged(); });
                }
                catch (InvalidOperationException)
                {
                    
                }
                
            }
        }

        protected override bool OnValueChanging(object newValue, object oldValue)
        {
            var isCancel = false;

            if (EditorCtrl != null && EditorCtrl.FindForm() != null)
            {
                try
                {
                    EditorCtrl.Invoke(() => { isCancel = base.OnValueChanging(newValue, oldValue); });
                }
                catch (InvalidOperationException)
                {
                    
                }
                
            }

            return isCancel;
        }

        protected virtual void OnControlValueChanged(object sender, EventArgs e)
        {
            base.OnSetBindObjectValue(OnGetControlValue());
        }

        protected abstract void OnDataFetherChanged();

        protected virtual void OnDataFetherShow()
        {
            DataFetcher.Show();
        }

        protected virtual void SetEditorEvent()
        {
            if (_editorCtrl!=null)
            {
                _editorCtrl.KeyDown += _editorCtrl_KeyDown;
                _editorCtrl.GotFocus += new EventHandler(_editorCtrl_GotFocus);
                _editorCtrl.LostFocus += new EventHandler(_editorCtrl_LostFocus);
            }
        }


        protected virtual void UnSetEditorEvent()
        {
            if (_editorCtrl != null)
            {
                _editorCtrl.KeyDown -= _editorCtrl_KeyDown;
            }
        }

        protected virtual void OnEditorCtrlChanged()
        {
            if (EditorCtrlChanged != null)
            {
                EditorCtrlChanged(this, EventArgs.Empty);
            }
        }

        protected virtual void OnEditorGetFoucs()
        {
            if (EditorCtrl!=null && EditorGetFocus!=null)
            {
                EditorCtrl.RaiseEvent(this.EditorGetFocus, this, EventArgs.Empty);
            }
        }

        protected virtual void OnEditorLostFoucs()
        {
            if (EditorCtrl != null && EditorLostFocus != null)
            {
                EditorCtrl.RaiseEvent(this.EditorLostFocus, this, EventArgs.Empty);
            }
        }

        protected virtual Control BuildLabelControl()
        {
            var label = new LabelX();
            
            label.Text = LabelText;

            label.AutoSize = true;

            label.BackColor = LabelBackColor;
            label.Font = LabelFont;
            label.ForeColor = LabelForeColor;

            return label;
        }

        public virtual Size GetLabelCtrlSize()
        {
            if (LabelCtrl!=null)
            {
                Graphics g = Graphics.FromHwnd(LabelCtrl.Handle);
                SizeF size = g.MeasureString(LabelCtrl.Text, LabelCtrl.Font);//获取大小  
                g.Dispose();

                return new Size((int)size.Width, (int)size.Height);
            }
            else
            {
                return new Size(0,0);
            }
        }


        private void _dataFetcher_DataFetherEnabledChanged(object sender, EventArgs e)
        {
            OnDataFetherChanged();
        }

        private void _editorCtrl_KeyDown(object sender, KeyEventArgs e)
        {


            if (e.KeyCode == Keys.Enter && !e.Control)
            {
                if (DataFetcher.HasDataFether)
                {
                    OnDataFetherShow();
                }

                e.Handled = true;
            }
        }

        private void _editorCtrl_GotFocus(object sender, EventArgs e)
        {
            OnEditorGetFoucs();
        }

        private void _editorCtrl_LostFocus(object sender, EventArgs e)
        {
            OnEditorLostFoucs();
        }


    }


    #region 各类控件

    public class Control_NumericFieldConfig : ControlFieldConfigBase
    {
        public Control_NumericFieldConfig(string id, object bindingObj = null)
            : base(id,bindingObj)
        {
            base.DataType = typeof(decimal);


        }

        public int DigitCount { set; get; }
        public decimal DefaultValue { set; get; }
        public decimal MaxValue { set; get; }
        public decimal MinValue { set; get; }

        internal override void ApplyToControl()
        {

            if (string.IsNullOrWhiteSpace(base.LabelText))
            {
                base.LabelText = FieldName;
            }

            LabelCtrl = BuildLabelControl();

            if (DigitCount == 0)
            {
                var tempEditCtrl = new IntegerInput();
                tempEditCtrl.Value = (int)DefaultValue;
                tempEditCtrl.MaxValue = (int)MaxValue;
                tempEditCtrl.MinValue = (int)MinValue;
                tempEditCtrl.ShowUpDown = true;


                tempEditCtrl.ButtonCustomClick += new EventHandler(tempEditCtrl_ButtonCustomClick);
                tempEditCtrl.ValueChanged += OnControlValueChanged;

                this.EditorCtrl = tempEditCtrl;
            }
            else
            {
                var tempEditCtrl = new DoubleInput();

                tempEditCtrl.Value = (double)DefaultValue;
                tempEditCtrl.MaxValue = (double)MaxValue;
                tempEditCtrl.MaxValue = (double)MinValue;
                tempEditCtrl.DisplayFormat = "0." + "0".PadRight(DigitCount);
                tempEditCtrl.ShowUpDown = true;
                tempEditCtrl.ButtonCustomClick += new EventHandler(tempEditCtrl_ButtonCustomClick);
                tempEditCtrl.ValueChanged += OnControlValueChanged;

                this.EditorCtrl = tempEditCtrl;
            }

            this.EditorCtrl.BackColor = EditorBackColor;
            this.EditorCtrl.Font = EditorFont;
            this.EditorCtrl.ForeColor = EditorForeColor;

            OnDataFetherChanged();
            OnIsNullableChanged();

            this.LabelCtrl.Text = LabelText;


        }

        protected override object OnGetControlValue()
        {
            if (EditorCtrl == null)
            {
                return DefaultValue;
            }

            object o = null;

            if (EditorCtrl is IntegerInput)
            {
                o = ((IntegerInput)EditorCtrl).ValueObject;
            }
            else
            {
                o = ((DoubleInput)EditorCtrl).ValueObject;
            }

            return Convert.ChangeType(o, DataType);
        }

        protected override void OnSetControlValue(object value)
        {
            object oldValue = null;

            oldValue = OnGetControlValue();

            if (oldValue != null && oldValue.Equals(value))
            {
                return;
            }
            else if (value != null && value.Equals(oldValue))
            {
                return;
            }
            else if (value == null && oldValue == null)
            {
                return;
            }

            if (value != oldValue)
            {
                if (EditorCtrl is IntegerInput)
                {
                    ((IntegerInput)EditorCtrl).Value = (int)value;
                }
                else
                {
                    ((DoubleInput)EditorCtrl).Value = (double)value;
                }
            }


        }

        protected override void OnIsNullableChanged()
        {
            base.OnIsNullableChanged();

            if (IsNullable)
            {
                DataType = typeof(decimal?);
            }
            else
            {
                DataType = typeof(decimal);
            }

            if (EditorCtrl is IntegerInput)
            {
                ((IntegerInput)EditorCtrl).ButtonClear.Visible = IsNullable;
            }
            else
            {
                ((DoubleInput)EditorCtrl).ButtonClear.Visible = IsNullable;
            }
        }

        protected override void OnDataFetherChanged()
        {
            if (EditorCtrl!=null)
            {
                ((NumericInputBase)EditorCtrl).ButtonCustom.Visible = base.DataFetcher.HasDataFether;
            }
        }

        void tempEditCtrl_ValueChanged(object sender, EventArgs e)
        {
            base.OnSetBindObjectValue(OnGetControlValue());

            //OnValueChanged();
        }

        void tempEditCtrl_ButtonCustomClick(object sender, EventArgs e)
        {
            base.DataFetcher.Show();
        }
    }

    public class Control_DateTimeFieldConfig : ControlFieldConfigBase
    {
        public Control_DateTimeFieldConfig(string id, object bindingObj = null)
            : base(id,bindingObj)
        {
            DataType = typeof(DateTime);
        }

        #region  字段相关参数

        public DateTime? DefaultValue { set; get; }

        public DateTime MaxValue { set; get; }

        public DateTime MinValue { set; get; }

        #endregion

        internal override void ApplyToControl()
        {
            if (string.IsNullOrWhiteSpace(base.LabelText))
            {
                base.LabelText = FieldName;
            }

            LabelCtrl = BuildLabelControl();

            var tempEditCtrl = new DateTimeInput();
            tempEditCtrl.ValueObject = DefaultValue;
            tempEditCtrl.MaxDate = MaxValue;
            tempEditCtrl.MinDate = MinValue;

            tempEditCtrl.ValueChanged += OnControlValueChanged;
            tempEditCtrl.ButtonCustomClick += tempEditCtrl_ValueChanged;

            this.EditorCtrl = tempEditCtrl;

            this.LabelCtrl.Text = LabelText;

            OnIsNullableChanged();
            OnDataFetherChanged();
        }

        #region 重写或实现的函数

        protected override object OnGetControlValue()
        {
            if (EditorCtrl == null)
            {
                return DefaultValue;
            }

            return Convert.ChangeType(((DateTimeInput)EditorCtrl).ValueObject, DataType);
        }

        protected override void OnSetControlValue(object value)
        {
            object oldValue = null;

            oldValue = OnGetControlValue();

            if (oldValue != null && oldValue.Equals(value))
            {
                return;
            }
            else if (value != null && value.Equals(oldValue))
            {
                return;
            }
            else if (value == null && oldValue == null)
            {
                return;
            }

            if (value != oldValue)
            {
                if (EditorCtrl is DevComponents.Editors.DateTimeAdv.DateTimeInput)
                {
                    ((DateTimeInput)EditorCtrl).Value = (DateTime)value;
                }
            }
        }

        protected override void OnIsNullableChanged()
        {
            base.OnIsNullableChanged();

            if (IsNullable)
            {
                DataType = typeof(DateTime?);
            }
            else
            {
                DataType = typeof(DateTime);
            }
        }

        protected override void OnDataFetherChanged()
        {
            if (EditorCtrl != null)
            {
                ((DateTimeInput)EditorCtrl).ButtonCustom.Visible = base.DataFetcher.HasDataFether;
            }
        }

        #endregion
        
        void tempEditCtrl_ValueChanged(object sender, EventArgs e)
        {
            base.OnSetBindObjectValue(OnGetControlValue());

            //OnValueChanged();
        }

        void tempEditCtrl_ButtonCustomClick(object sender, EventArgs e)
        {
            base.DataFetcher.Show();
        }

    }

    public class Control_TextFieldConfig : ControlFieldConfigBase
    {
        public Control_TextFieldConfig(string id, object bindingObj = null)
            : base(id,bindingObj)
        {
            base.DataType = typeof(string);
        }

        public int MaxLength { set; get; }
        public string DefaultValue { set; get; }
        public bool EnableMutliLine { set; get; }
        public string WatermarkValue { set; get; }

        internal override void ApplyToControl()
        {
            if (string.IsNullOrWhiteSpace(base.LabelText))
            {
                base.LabelText = FieldName;
            }

            LabelCtrl = BuildLabelControl();

            var tempEditCtrl = new TextBoxX();

            tempEditCtrl.Text = DefaultValue;
            tempEditCtrl.WatermarkText = WatermarkValue;
            tempEditCtrl.MaxLength = MaxLength;
            tempEditCtrl.Multiline = EnableMutliLine;

            tempEditCtrl.TextAlign = HorizontalAlignment.Left;

            

            tempEditCtrl.ButtonCustomClick += tempEditCtrl_ButtonCustomClick;
            tempEditCtrl.TextChanged += tempEditCtrl_ValueChanged;
           
            EditorCtrl = tempEditCtrl;
        }

        protected override object OnGetControlValue()
        {
            if (EditorCtrl == null)
            {
                return DefaultValue;
            }

            return ((TextBoxX)EditorCtrl).Text;
        }

        protected override void OnSetControlValue(object value)
        {
            object oldValue = null;

            oldValue = OnGetControlValue();

            if (oldValue.SafeEquals(value))
            {
                return;
            }


            if (value != oldValue)
            {
                if (EditorCtrl is TextBoxX)
                {
                    ((TextBoxX)EditorCtrl).Text = (string)value;
                }
            }
        }

        protected override void OnDataFetherChanged()
        {
            if (EditorCtrl != null)
            {
                ((TextBoxX)EditorCtrl).ButtonCustom.Visible = base.DataFetcher.HasDataFether;
            }
        }

        void tempEditCtrl_ValueChanged(object sender, EventArgs e)
        {
            base.OnSetBindObjectValue(OnGetControlValue());

            //OnValueChanged();
        }

        void tempEditCtrl_ButtonCustomClick(object sender, EventArgs e)
        {
            base.DataFetcher.Show();
        }
    }

    public class Control_LabelFiledConfig:ControlFieldConfigBase
    {
        public Control_LabelFiledConfig(string id, object bindingObj=null)
            : base(id,bindingObj)
        {
            DataType = typeof(string);
        }

        internal override void ApplyToControl()
        {
            LabelX tempCtrl = null;

            if (this.EditorCtrl != null)
            {
                tempCtrl = new LabelX();

                tempCtrl.BackgroundStyle.Class = "";
                tempCtrl.BackgroundStyle.CornerType = eCornerType.Square;
                tempCtrl.Size = new Size(68, 19);

                EditorCtrl = tempCtrl;
            }
            else
            {
                tempCtrl = (LabelX) this.EditorCtrl;
            }

            tempCtrl.AutoSize = true;
            tempCtrl.Text = "";

        }

        protected override object OnGetControlValue()
        {
            return EditorCtrl.Text;
        }

        protected override void OnSetControlValue(object value)
        {
            EditorCtrl.Text = value.ToStringEx();
        }

        protected override void OnDataFetherChanged()
        {
            //throw new NotImplementedException();
        }
    }

    public class Control_ButtonFieldConfig:ControlFieldConfigBase
    {
        public Control_ButtonFieldConfig(string id) : base(id, null)
        {
        }

        public event EventHandler ButtonClick;

        internal override void ApplyToControl()
        {
            ButtonX tempBtn = null;

            if (this.EditorCtrl==null)
            {
                tempBtn = new ButtonX();

                tempBtn.AccessibleRole = AccessibleRole.PushButton;
                tempBtn.ColorTable = eButtonColor.OrangeWithBackground;
                tempBtn.Enabled = true;
                tempBtn.Margin = new System.Windows.Forms.Padding(2);
                tempBtn.Shape = new RoundRectangleShapeDescriptor(7);
                tempBtn.Size = new Size(75, 35);
                tempBtn.Style = eDotNetBarStyle.StyleManagerControlled;
                tempBtn.Click += OnButtonClick;
            }
            else
            {
                tempBtn = (ButtonX) this.EditorCtrl;
            }

            tempBtn.Text = this.LabelText;

        }

        protected override void OnLabelTextChanged()
        {
            base.OnLabelTextChanged();

            if (this.EditorCtrl!=null)
            {
                this.EditorCtrl.Text = this.LabelText;
            }
        }

        protected override object OnGetControlValue()
        {
            return null;
        }

        protected override void OnSetControlValue(object value)
        {
            
        }

        protected override void OnDataFetherChanged()
        {
            
        }

        private  void OnButtonClick(object sender, EventArgs e)
        {
            if (ButtonClick!=null)
            {
                ButtonClick(this.EditorCtrl, EventArgs.Empty);
            }
        }
    }

    #endregion



    
}
